/**************************************************************/
/*                                                            */
/*     MC823 - Laboratorio de Teleprocessamento e Redes       */
/*     1 Semestre / 2013                                      */
/*     Projeto 1 - Cliente e Servidor RMI de uma Livraria     */
/*                                                            */
/*     Alunos: Joao Gabriel M.D.Mendes - RA 102788            */
/*             Lucas Domingues Lima    - RA 103140            */
/*                                                            */
/**************************************************************/

/* Arquivo: livraria/rmi/src/Client.java
   Definicao: Classe Cliente, que carrega os possiveis ISBNs de
   			  um arquivo externo e simula 100 requisicoes de
   			  cada um dos 6 tipos, em ordem aleatoria. 
   			  Para rodar: java livraria/rmi/Client user_id server_ip
*/


package livraria.rmi;

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.Random;
import java.io.*;
import java.util.Scanner;
import java.lang.System;

public class Client {

    private Client() {}
    private static int NANOPERSEC = 1000000000;
    
    //possiveis ISBNs a serem utilizados nas requisicoes.
    private static String[] reqs;
    private static String Reqs_file = "../ISBNs.txt";
    //tamanho maximo e tamanho real do vetor de ISBNs.
    private static int max_size = 30;
    private static int size;
    
    
    //inicializa o vetor reqs[] com os possiveis ISBNs a serem requeridos
    //do servidor.
    private static void loadReqs() {
    	try {
			Scanner in = new Scanner(new FileReader(Reqs_file));
				reqs = new String[max_size];
				int i = 0;
				
				while(in.hasNextLine() && (i < max_size)) {
					reqs[i] = in.nextLine();
					i++;
				}
				size = i;
				in.close();
		}catch (Exception e) {
			System.err.println("t_estoque exception: " + e.toString());
			e.printStackTrace();
		}
    }

    public static void main(String[] args) {
		
		if(args.length < 1) {
			System.err.println("Usage: java livraria.rmi.Server client_id host_address");
			return;
		}
		//identificacao do cliente. 
		String id = args[0];
		//se nao for passado host, host usado e nulo, para testes
		//locais (cliente e servidor na mesma maquina).
		String host = (args.length < 2) ? null : args[1];
		
		try {
			//sets up remote object
			Registry registry = LocateRegistry.getRegistry(host);
			Livraria stub = (Livraria) registry.lookup("Livraria");
			
			//initializes this.reqs[]
			loadReqs();
			
			//initializes random generators for requisitions simulation
			Random reqTypeGenerator = new Random();
			Random ISBNindxGenerator = new Random();
			Random numGenerator = new Random();
			int i;
			int[] count = new int[6];
			
			//zera contador de requisicoes para cada tipo
			for(i=0;i<6;i++) count[i]=0;
			i = 0;
			String response = "";
			
			//cria arquivos dos logs do cliente (de eventos e de tempos)
			PrintWriter logwriter = new PrintWriter("client_"+id+".log", "UTF-8");
			PrintWriter twriter = new PrintWriter("client_"+id+".time", "UTF-8");
			
			while(i<600) {
				//gera um tipo de requisicao, um ISBN da lista
				//e uma quantidade de 0 a 100 de forma aleatoria.
				int req_num = reqTypeGenerator.nextInt(6);
				String ISBN_curr = reqs[ISBNindxGenerator.nextInt(size)];
				int qtd_num = numGenerator.nextInt(100);
				//nao faz mais que 100 requisicoes do mesmo tipo,
				//em uma unica execucao.
				if(count[req_num] >= 100) continue;
				i++;
				//pega o tempo inicial
				long t_start = System.nanoTime();
				
				//de acordo com o tipo de requisicao, faz a respectiva
				//chamada no stub local para o objeto remoto no servidor.
				switch(req_num) {
					case 0:	response = stub.retornaTitulosISBN(id);
							break;
							
					case 1: response = stub.retornaInfoEstoque(id);
							break;
							
					case 2: response = stub.retornaDescricao(id,ISBN_curr);
							break;
					
					case 3: response = stub.retornaInfoLivro(id,ISBN_curr);
							break;
					
					case 4: response = stub.retornaNumLivro(id,ISBN_curr);
							break;
					
					case 5: response = stub.alteraEstoque(id,ISBN_curr,qtd_num);
							break;
				}
				//para o contador de tempo e escreve no log de tempo e de evento.
				//precisao de nanoTime() limitada ao temporizador mais
				//preciso disponivel. Nanossegundos no Linux Ubuntu,
				//Microssegundos no Macintosh
				long t_stop = System.nanoTime();
				double timeSpent = (double)(t_stop - t_start)/NANOPERSEC;
				String time = String.format("%d %.9f",req_num,timeSpent);
				twriter.println(time);
				String requested = "requested: %s | ISBN: %s | qtd: %s";
				logwriter.println(String.format(requested,
						Integer.toString(req_num),ISBN_curr,Integer.toString(qtd_num)));
				logwriter.println("response: " + response);
				
			}
			logwriter.close();
			twriter.close();
		} catch (Exception e) {
			System.err.println("Client exception: " + e.toString());
			e.printStackTrace();
		}
    }
}